home *** CD-ROM | disk | FTP | other *** search
- /**
- GRAB Graph Layout and Browser System
-
- Copyright (c) 1986, 1988 Regents of the University of California
- Copyright (c) 1989, Tera Computer Company
- **/
-
- /**
- change.c - routines for changing attributes of a node, an edge, or edges
- associated with a node.
-
- Nodes, edges, and the in and out edges of a node can have their attributes
- set to match the built-in attributes display, or reset to their default
- values. In addition, nodes and edges can be cycled through all possible
- values of their attributes
-
- An attribute is *never* changed if the built-in attributes display says
- there is no value for that attribute. So, for example, if the BIAD shows
- a shape of 'circle', a brush of 'no brush', and a color of 'white', a
- set will only set a node's shape and color (and a reset will not reset
- a node's brush!). The shape attribute, of course, has no affect on
- edges.
-
- For the purposes of cycling, shape can be considered the 'least significant'
- attribute and color the 'most significant'. So a node will first cycle
- through all shapes, keeping the same color and brush. When the shape
- changes to the first shape (rectangle), the brush changes, too, and so on.
- This, again, is subject to the restrictions in the previous paragraph; if
- the current shape is 'no shape', brush becomes the least significant
- attribute, and if the current brush is 'no brush;, color is the least
- significant.
- **/
-
- #include "attribute.h"
- #include "digraph.h"
- #include "globals.h"
- #include "interf.h"
- #include "tedge.h"
-
- extern NODE *next_dummy(), *prev_dummy();
- extern BOOL edge_on_screen(), on_screen();
- extern OUTEDGE *get_edge();
-
- void DoCycleEdge()
- /* set an edge's attributes to the 'next' value */
- {
- TEDGE* t;
- BRUSH brush;
- COLOR color;
- OUTEDGE* e;
-
- t = (TEDGE *) ICurEdge();
- e = get_edge(digraph, (NODE *) t->fromnode, (NODE *) t->tonode, t->ord);
-
- brush = INextBrush(Brush(e));
-
- if (!IBrushSet() || brush == SOLIDB)
- /* brush has no value or brush has caused a 'carry' */
- {
- color = INextColor(Color(e));
- }
- else
- {
- color = Color(e);
- }
-
- ChangeEdge((NODE *) t->fromnode, (NODE *) t->tonode, brush, color, t->ord);
- }
-
- void DoSetEdge()
- /**
- set an edge's attributes to the values displayed in the built-in
- attribute display
- **/
- {
- TEDGE* t;
- BRUSH brush;
- COLOR color;
-
- brush = ICurBrush();
- color = ICurColor();
- t = (TEDGE *) ICurEdge();
- ChangeEdge((NODE *) t->fromnode, (NODE *) t->tonode, brush, color, t->ord);
- }
-
- void DoResetEdge()
- /**
- reset an edge's attributes
- **/
- {
- TEDGE *t;
-
- t = (TEDGE *) ICurEdge();
- ChangeEdge((NODE *) t->fromnode, (NODE *) t->tonode, DEFAULT_BRUSH,
- DEFAULT_COLOR, t->ord);
- }
-
- ChangeEdge(from, to, brush, color, ord)
- NODE *from, *to;
- BRUSH brush;
- COLOR color;
- int ord;
- /**
- Handy edge changing routine: change the edge from from to to with
- ordinality ord so it has brush brush and color color (got that?)
- However, don't change the brush if the current brush is 'no brush', or
- the color if the current color is 'no color'.
-
- If the edge is on the screen, it must be redisplayed. If one of
- the endpoints of the edge is a dummy node, it's only a subedge and
- the rest of it must be changed, also.
- **/
- {
- OUTEDGE* e;
-
- e = get_edge(digraph, from, to, ord);
-
- if (IColorSet())
- {
- Color(e) = color;
- }
-
- if (IBrushSet())
- {
- Brush(e) = brush;
- }
-
- if (edge_on_screen(from, to))
- {
- IChangeEdge(from, to, ord, Brush(e), Color(e));
- }
-
- if (Is_dummy(to))
- {
- ChangeToDummyEdges(to, ord, Brush(e), Color(e));
- }
-
- if (Is_dummy(from))
- {
- ChangeFromDummyEdges(from, ord, Brush(e), Color(e));
- }
-
- graphChanged = TRUE; /* the times, they are a changin' */
- ckpt_done = FALSE;
- }
-
- void DoCycleNode()
- /* set a node's attributes to the 'next' value */
- {
- NODE *node;
- SHAPE shape;
- BRUSH brush;
- COLOR color;
-
- node = (NODE *) ICurNode();
- shape = INextShape(Shape(node));
-
- if (!IShapeSet() || shape == RECTANGLE)
- /* if the shape doesn't change, or the shape generated a 'carry' */
- {
- brush = INextBrush(Brush(node));
-
- if (!IBrushSet() || brush == SOLIDB)
- /* if the brush doesn't change, or the brush generated a 'carry' */
- {
- color = INextColor(Color(node));
- }
- else
- {
- color = Color(node);
- }
- }
- else
- {
- brush = Brush(node);
- color = Color(node);
- }
-
- ChangeNode(node, shape, brush, color);
- }
-
- void DoSetNode()
- /**
- set a node's attributes to the values displayed in the built-in
- attribute display
- **/
- {
- NODE *node;
- SHAPE shape;
- BRUSH brush;
- COLOR color;
-
- node = (NODE *) ICurNode();
- shape = ICurShape();
- brush = ICurBrush();
- color = ICurColor();
-
- ChangeNode(node, shape, brush, color);
- }
-
- void DoResetNode()
- /**
- reset a node's attributes
- **/
- {
- NODE *node;
-
- node = (NODE *) ICurNode();
-
- ChangeNode(node, DEFAULT_SHAPE, DEFAULT_BRUSH, DEFAULT_COLOR);
- }
-
- ChangeNode(node, shape, brush, color)
- NODE *node;
- SHAPE shape;
- BRUSH brush;
- COLOR color;
- /**
- Handy node changing routine: change node
- so it has shape shape, brush brush, and color color (got that?)
- However, don't change the shape if the current shape is 'no shape',
- the brush if the current brush is 'no brush', or
- the color if the current color is 'no color'.
-
- If the node is on the screen, it must be redisplayed (I really wonder
- how it could fail to be so).
- **/
- {
- if (IShapeSet())
- {
- Shape(node) = shape;
- }
-
- if (IColorSet())
- {
- Color(node) = color;
- }
-
- if (IBrushSet())
- {
- Brush(node) = brush;
- }
-
- if (on_screen(node))
- {
- IChangeNode(node, Shape(node), Brush(node), Color(node));
- }
-
- graphChanged = TRUE; /* I'm a changeling... see me change */
- ckpt_done = FALSE;
- }
-
- void DoSetEdges()
- /**
- set the attributes of the in/out edges of the current node
- to the values displayed in the built-in attribute display
- **/
- {
- NODE *node;
- BRUSH brush;
- COLOR color;
-
- node = (NODE *) ICurNode();
- brush = ICurBrush();
- color = ICurColor();
-
- if (changeOutEdges)
- {
- ChangeOutEdges(node, brush, color);
- }
-
- if (changeInEdges)
- {
- ChangeInEdges(node, brush, color);
- }
- }
-
- void DoResetEdges()
- /**
- reset the attributes of the in/out edges of the current node
- **/
- {
- NODE* node;
-
- node = (NODE *) ICurNode();
-
- if (changeOutEdges)
- {
- ChangeOutEdges(node, DEFAULT_BRUSH, DEFAULT_COLOR);
- }
-
- if (changeInEdges)
- {
- ChangeInEdges(node, DEFAULT_BRUSH, DEFAULT_COLOR);
- }
- }
-
- ChangeOutEdges(node, brush, color)
- NODE *node;
- BRUSH brush;
- COLOR color;
- /**
- Not as easy as it may seem. You see, the inedges of a node are
- really 'up edges' (edges that go to nodes above this one in the graph).
- Similarly, outedges are 'down edges'. And, of course, antecedents and
- succedents could more aptly be called upstairs and downstairs neighbors.
- So, to find the true in/out edges of a node, you have to look at
- both the antecedent and succedent sets.
-
- Outedges are edges to succedents that aren't reversed and from
- antecedents that are.
- **/
- {
- VNO toVno; /* each succedent node */
- NODE *toNode;
- OUTEDGE *e;
- int i;
-
- each_element(Succ_set(node), toVno)
- loop
- toNode = Node(digraph, toVno);
-
- for (i = max_edges(node, toNode); i > 0; i--)
- {
- if ((e = get_edge(digraph, node, toNode, i)) != NULL &&
- !Edge_reversed(e))
- {
- ChangeEdge(node, toNode, brush, color, i);
- }
- }
- endloop;
-
- each_element(Ante_set(node), toVno)
- loop
- toNode = Node(digraph, toVno);
-
- for (i = max_edges(toNode, node); i > 0; i--)
- {
- if ((e = get_edge(digraph, toNode, node, i)) != NULL &&
- Edge_reversed(e))
- {
- ChangeEdge(toNode, node, brush, color, i);
- }
- }
- endloop;
- }
-
- ChangeInEdges(node, brush, color)
- NODE *node;
- BRUSH brush;
- COLOR color;
- /**
- See the note to ChangeOutEdges, above.
-
- Inedges are edges to succedents that are reversed and from
- antecedents that aren't.
- **/
- {
- VNO fromVno; /* each antecedent node */
- NODE *fromNode;
- OUTEDGE *e;
- int i;
-
- each_element(Ante_set(node), fromVno)
- loop
- fromNode = Node(digraph, fromVno);
-
- for (i = max_edges(fromNode, node); i > 0; i--)
- {
- if ((e = get_edge(digraph, fromNode, node, i)) != NULL &&
- !Edge_reversed(e))
- {
- ChangeEdge(fromNode, node, brush, color, i);
- }
- }
- endloop;
-
- each_element(Succ_set(node), fromVno)
- loop
- fromNode = Node(digraph, fromVno);
-
- for (i = max_edges(node, fromNode); i > 0; i--)
- {
- if ((e = get_edge(digraph, node, fromNode, i)) != NULL &&
- Edge_reversed(e))
- {
- ChangeEdge(node, fromNode, brush, color, i);
- }
- }
- endloop;
- }
-
- ChangeToDummyEdges(fromNode, ord, brush, color)
- NODE *fromNode;
- int ord;
- BRUSH brush;
- COLOR color;
- /**
- Change the edge from fromNode of ordinality ord until we hit a non-dummy.
- fromNode had better be a dummy node itself.
- **/
- {
- NODE *node, *toNode;
-
- node = fromNode;
- toNode = next_dummy(digraph, node);
-
- /* change edge until non-dummy node */
- do
- {
- if (edge_on_screen(node, toNode))
- {
- IChangeEdge(node, toNode, ord, brush, color);
- }
-
- node = toNode;
- toNode = next_dummy(digraph, node);
- } while (Is_dummy(node));
- }
-
- ChangeFromDummyEdges(node, ord, brush, color)
- NODE *node;
- int ord;
- BRUSH brush;
- COLOR color;
- /**
- Change the edge to node of ordinality ord until we hit a non-dummy.
- node had better be a dummy node itself.
- **/
- {
- NODE *fromNode;
-
- fromNode = prev_dummy(digraph, node);
-
- do
- {
- if (edge_on_screen(fromNode, node))
- {
- IChangeEdge(fromNode, node, ord, brush, color);
- }
-
- node = fromNode;
- fromNode = prev_dummy(digraph, node);
- } while (Is_dummy(node));
- }
-